import { Provide } from '@midwayjs/core';

const cryptoRandom = require("math-random");

@Provide()
export class CustomIdUtils {

  customId(customId: any) {
    if (typeof customId === "undefined") {
      throw new Error(
        "Custom Id expects an object as the argument. Make sure all values of that object are string."
      );
    }
    const multiply = customId.uniqueId || 97232;
    const crypticNotSecure = Math.floor(Math.random() * multiply);
    const crypticSecureFun = cryptoRandom() * multiply;
    const crypticSecure = Math.floor(crypticSecureFun);
    const length = customId.randomLength || 2;
    const firstId = this.idGenerate(
      length,
      crypticSecure.toString() || crypticNotSecure.toString()
    );
    let key1: any, key2: any, key3: any;
    if (customId.key1) {
      key1 = this.idGenerate(
        length,
        customId.key1.replace(/[^a-zA-Z0-9]/g, "").toString() || ""
      );
    } else {
      key1 = this.idGenerate(length, "ABCDEFGHIJKLMNOPQRSTUVXYZ");
    }
    if (customId.key2) {
      key2 = this.idGenerate(
        length,
        customId.key2.replace(/[^a-zA-Z0-9]/g, "").toString() || ""
      );
    } else {
      key2 = this.idGenerate(length, "ABCDEFGHIJKLMNOPQRSTUVXYZ");
    }

    if (customId.key3) {
      key3 = this.idGenerate(
        length,
        customId.key3.replace(/[^a-zA-Z0-9]/g, "").toString() || ""
      );
    } else {
      key3 = this.idGenerate(length, "ABCDEFGHIJKLMNOPQRSTUVXYZ");
    }

    const lastId = this.idGenerate(
      length,
      crypticSecure.toString() || crypticNotSecure.toString()
    );
    const result = key1 + firstId + key2 + lastId + key3;

    return customId.lowerCase ? result.toLowerCase() : result.toUpperCase();
  }

  idGenerate(x?: number, y?: string): string {
    let length =
      arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 12;
    let scope =
      arguments.length > 1 && arguments[1] !== undefined
        ? arguments[1]
        : "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    if (typeof length !== "number") throw new Error("length must be a number");
    if (typeof scope !== "string") throw new Error("scope must be a string");
    let str = "";
    let l = scope.length;

    for (let i = 0; i < length; i++) {
      str += scope.charAt(Math.floor(Math.random() * l));
    }
    return str;
  }
}